use log::info;
use log::trace;
use serde::{ Deserialize, Serialize };
use serde_json::Value;

use anyhow::anyhow;
use anyhow::Result;

use crate::REQWEST_CLIENT;

/// 历史净值
///
/// 净值日期	单位净值	累计净值	日增长率	申购状态	赎回状态
///
/// Mapping to [FUND_jjjz_000001.json](file:///Users/CC/gitee/conanchen/fuquants-workspace/crates/fudacli/eastmoney/sample/FUND_jjjz_000001.json)
#[derive(Debug, Serialize, Deserialize)]
pub struct FundJjjz {
    #[serde(rename = "Data")]
    pub data: FundJjjzData, // 基金净值数据
    #[serde(rename = "ErrCode")]
    pub err_code: Option<Value>, // 错误码
    #[serde(rename = "ErrMsg")]
    pub err_msg: Option<Value>, // 错误信息
    #[serde(rename = "TotalCount")]
    pub total_count: Option<Value>, // 总记录数
    #[serde(rename = "Expansion")]
    pub expansion: Option<Value>, // 扩展数据
    #[serde(rename = "PageSize")]
    pub page_size: Option<Value>, // 每页记录数
    #[serde(rename = "PageIndex")]
    pub page_index: Option<Value>, // 当前页码
}
#[derive(Debug, Serialize, Deserialize)]
pub struct FundJjjzData {
    #[serde(rename = "LSJZList")]
    pub lsjz_list: Vec<FundJjjzDataItem>, // 净值列表
    #[serde(rename = "FundType")]
    pub fund_type: Option<Value>, // 基金类型
    #[serde(rename = "SYType")]
    pub sy_type: Option<Value>, // 收益类型
    #[serde(rename = "isNewType")]
    pub is_new_type: Option<Value>, // 是否新类型
    #[serde(rename = "Feature")]
    pub feature: Option<Value>, // 特征
}

/// 净值日期	单位净值	累计净值	日增长率	申购状态	赎回状态
#[derive(Debug, Serialize, Deserialize)]
pub struct FundJjjzDataItem {
    #[serde(rename = "FSRQ")]
    pub fsrq: Option<Value>, // 公布日期
    #[serde(rename = "DWJZ")]
    pub dwjz: Option<Value>, // 单位净值
    #[serde(rename = "LJJZ")]
    pub ljjz: Option<Value>, // 累计净值
    #[serde(rename = "SDATE")]
    pub sdate: Option<Value>, // 起始日期
    #[serde(rename = "ACTUALSYI")]
    pub actual_syi: Option<Value>, // 实际收益率
    #[serde(rename = "NAVTYPE")]
    pub nav_type: Option<Value>, // 净值类型
    #[serde(rename = "JZZZL")]
    pub jzzzl: Option<Value>, // 涨跌幅 净值增长率
    #[serde(rename = "SGZT")]
    pub sgzt: Option<Value>, // 申购状态
    #[serde(rename = "SHZT")]
    pub shzt: Option<Value>, // 赎回状态
    #[serde(rename = "FHFCZ")]
    pub fhfcz: Option<Value>, // 复盘前收盘价
    #[serde(rename = "FHFCBZ")]
    pub fhfcbz: Option<Value>, // 复盘前涨跌幅
    #[serde(rename = "DTYPE")]
    pub dtype: Option<Value>, // 数据类型
    #[serde(rename = "FHSP")]
    pub fhsp: Option<Value>, // 复盘时间
}
impl FundJjjz {
    /// Refer to: https://fundf10.eastmoney.com/jjjz_000001.html 历史净值
    ///
    /// Data: https://api.fund.eastmoney.com/f10/lsjz?fundCode=000001&pageIndex=2&pageSize=20&startDate=&endDate=&_=1709103079998
    ///
    /// code: e.g. 000001
    ///
    /// page_index: e.g. 1, page index to retrieve
    ///
    /// page_size: e.g. 10 , page size to retrieve
    pub async fn fund_jjjz(
        worker_no: u8,
        code: &str,
        page_index: u32,
        page_size: u32
    ) -> Result<FundJjjz> {
        trace!("Worker[{worker_no}] fund_jjjz---1");
        // GET /f10/lsjz?callback=jQuery18305696692936409764_1709103066282&fundCode=000001&pageIndex=2&pageSize=20&startDate=&endDate=&_=1709103079998 HTTP/1.1
        // Accept: */*
        // Accept-Encoding: gzip, deflate, br
        // Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
        // Cache-Control: no-cache
        // Connection: keep-alive
        // Cookie: qgqp_b_id=d6299473145338f68687834ba37fa719; st_si=77687174285423; AUTH_FUND.EASTMONEY.COM_GSJZ=AUTH*TTJJ*TOKEN; EMFUND0=01-29%2015%3A02%3A07@%23%24%u534E%u590F%u4E2D%u8BC1%u5168%u6307%u623F%u5730%u4EA7ETF@%23%24515060; EMFUND1=01-30%2014%3A41%3A22@%23%24%u534E%u6CF0%u67CF%u745E%u6D88%u8D39%u6210%u957F%u6DF7%u5408@%23%24001069; EMFUND2=01-30%2014%3A45%3A59@%23%24%u5E7F%u53D1%u6052%u751F%u6D88%u8D39%28QDII-ETF%29@%23%24159699; EMFUND3=01-30%2014%3A47%3A24@%23%24%u5357%u65B9%u7EA2%u5229%u4F4E%u6CE250ETF@%23%24515450; EMFUND4=01-31%2015%3A21%3A23@%23%24%u56FD%u8054%u4E2D%u8BC1%u7164%u70AD%u6307%u6570%28LOF%29A@%23%24168204; EMFUND5=02-02%2008%3A34%3A56@%23%24%u666F%u987A%u957F%u57CE%u652F%u67F1%u4EA7%u4E1A%u6DF7%u5408@%23%24260117; EMFUND6=02-02%2010%3A30%3A22@%23%24%u897F%u90E8%u5229%u5F97%u805A%u79BE%u6DF7%u5408A@%23%24007423; EMFUND7=02-26%2016%3A07%3A01@%23%24%u91D1%u9E70%u6DFB%u76C8%u7EAF%u503A%u503A%u5238A@%23%24003384; EMFUND8=02-27%2010%3A51%3A37@%23%24%u534E%u590F%u6210%u957F%u6DF7%u5408@%23%24000001; EMFUND9=02-27 13:53:07@#$%u534E%u6CF0%u67CF%u745E%u5357%u65B9%u4E1C%u82F1%u6052%u751F%u79D1%u6280%28QDII-ETF%29@%23%24513130; st_asi=delete; HAList=ty-0-000001-%u8D27%u5E01ETF%2Cty-0-000001-%u5E73%u5B89%u94F6%u884C%2Cty-0-161127-%u6807%u666E%u751F%u7269%u79D1%u6280LOF%2Cty-1-513130-%u6052%u751F%u79D1%u6280ETF%2Cty-0-300078-%u601D%u521B%u533B%u60E0%2Cty-0-300486-%u4E1C%u6770%u667A%u80FD%2Cty-1-513360-%u6559%u80B2ETF%2Cty-0-300478-%u676D%u5DDE%u9AD8%u65B0%2Cty-0-301589-N%u8BFA%u74E6%2Cty-1-603135-%u4E2D%u91CD%u79D1%u6280; st_pvi=47260449691882; st_sp=2024-01-12%2017%3A28%3A27; st_inirUrl=https%3A%2F%2Fwww.google.com.hk%2F; st_sn=705; st_psi=20240228145106209-112200305283-5573227163
        // Host: api.fund.eastmoney.com
        // Pragma: no-cache
        // Referer: https://fundf10.eastmoney.com/
        // Sec-Fetch-Dest: script
        // Sec-Fetch-Mode: no-cors
        // Sec-Fetch-Site: same-site
        // User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36
        // sec-ch-ua: "Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"
        // sec-ch-ua-mobile: ?0
        // sec-ch-ua-platform: "macOS"

        let host = "api.fund.eastmoney.com";
        // Query String Parameters:
        //
        // callback: jQuery18305696692936409764_1709103066282
        // let fundCode= "000001";
        // let page_index = 1;
        // let page_size = limit;
        // startDate:
        // endDate:
        let t_ = utils::duration_ms_since_epoch(); // 1709103079998

        let request_url = format!(
            "https://{host}/f10/lsjz?fundCode={code}&pageIndex={page_index}&pageSize={page_size}&startDate=&endDate=&_={t_}"
        );
        info!("\n (fund_jjjz) request_url= {}\n", request_url);

        let response_rs = REQWEST_CLIENT.get(request_url)
            .header(reqwest::header::ACCEPT, "*/*")
            .header(reqwest::header::ACCEPT_ENCODING, "gzip, deflate, br")
            .header(reqwest::header::ACCEPT_LANGUAGE, "zh-CN,zh;q=0.9,en;q=0.8")
            .header(reqwest::header::CACHE_CONTROL, "no-cache")
            .header(reqwest::header::CONNECTION, "keep-alive")
            // .header(reqwest::header::COOKIE, "qgqp_b_id=d6299473145338f68687834ba37fa719; st_si=77687174285423; AUTH_FUND.EASTMONEY.COM_GSJZ=AUTH*TTJJ*TOKEN; EMFUND0=01-16%2016%3A57%3A06@%23%24%u4E2D%u822A%u65B0%u8D77%u822A%u7075%u6D3B%u914D%u7F6E%u6DF7%u5408A@%23%24005537; EMFUND1=01-16%2017%3A04%3A53@%23%24%u91D1%u4FE1%u6D88%u8D39%u5347%u7EA7%u80A1%u7968A@%23%24006692; EMFUND2=01-16%2020%3A01%3A56@%23%24%u5357%u65B9%u4E0A%u8BC1380ETF@%23%24510290; EMFUND3=01-29%2015%3A02%3A07@%23%24%u534E%u590F%u4E2D%u8BC1%u5168%u6307%u623F%u5730%u4EA7ETF@%23%24515060; EMFUND4=01-30%2014%3A41%3A22@%23%24%u534E%u6CF0%u67CF%u745E%u6D88%u8D39%u6210%u957F%u6DF7%u5408@%23%24001069; EMFUND5=01-30%2014%3A45%3A59@%23%24%u5E7F%u53D1%u6052%u751F%u6D88%u8D39%28QDII-ETF%29@%23%24159699; EMFUND6=01-30%2014%3A47%3A24@%23%24%u5357%u65B9%u7EA2%u5229%u4F4E%u6CE250ETF@%23%24515450; EMFUND7=01-31%2015%3A21%3A23@%23%24%u56FD%u8054%u4E2D%u8BC1%u7164%u70AD%u6307%u6570%28LOF%29A@%23%24168204; EMFUND8=02-02%2008%3A34%3A56@%23%24%u666F%u987A%u957F%u57CE%u652F%u67F1%u4EA7%u4E1A%u6DF7%u5408@%23%24260117; EMFUND9=02-02 10:30:22@#$%u897F%u90E8%u5229%u5F97%u805A%u79BE%u6DF7%u5408A@%23%24007423; st_asi=delete; HAList=ty-1-513130-%u6052%u751F%u79D1%u6280ETF%2Cty-0-300078-%u601D%u521B%u533B%u60E0%2Cty-0-300486-%u4E1C%u6770%u667A%u80FD%2Cty-1-513360-%u6559%u80B2ETF%2Cty-0-300478-%u676D%u5DDE%u9AD8%u65B0%2Cty-0-301589-N%u8BFA%u74E6%2Cty-1-603135-%u4E2D%u91CD%u79D1%u6280%2Cty-0-000001-%u5E73%u5B89%u94F6%u884C%2Cty-0-002400-%u7701%u5E7F%u96C6%u56E2%2Cty-1-601127-%u8D5B%u529B%u65AF; st_pvi=47260449691882; st_sp=2024-01-12%2017%3A28%3A27; st_inirUrl=https%3A%2F%2Fwww.google.com.hk%2F; st_sn=438; st_psi=20240226102321941-113200301321-9024721593")
            .header(reqwest::header::HOST, format!("{host}"))
            .header(reqwest::header::PRAGMA, "no-cache")
            .header(reqwest::header::REFERER, "https://fundf10.eastmoney.com/")
            .header(
                reqwest::header::USER_AGENT,
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
            )
            .header(
                "Sec-Ch-Ua",
                "\"Not A(Brand\";v=\"99\", \"Google Chrome\";v=\"121\", \"Chromium\";v=\"121\""
            )
            .header("Sec-Ch-Ua-Mobile", "?0")
            .header("Sec-Ch-Ua-Platform", "\"macOS\"")
            .header("Sec-Fetch-Dest", "empty")
            .header("Sec-Fetch-Mode", "cors")
            .header("Sec-Fetch-Site", "same-origin")
            .send().await;
        trace!("Worker[{worker_no}] fund_jjjz---2");

        match response_rs {
            Ok(response) => {
                trace!("Worker[{worker_no}] fund_jjjz---2.1.1");
                let body_rs = response.text().await;
                trace!("Worker[{worker_no}] fund_jjjz---2.1.2");

                match body_rs {
                    Ok(body) => {
                        // println!("*** body={}\n\nhangqin\n\n", body);

                        let fund_rs = serde_json::from_str::<FundJjjz>(&body);
                        match fund_rs {
                            Ok(fund) => {
                                trace!("Worker[{worker_no}] fund_jjjz---2.2");
                                return Ok(fund);
                            }
                            Err(e) => {
                                trace!("Worker[{worker_no}] fund_jjjz---2.3");
                                return Err(anyhow!(e));
                            }
                        }
                        // println!("{:?}", fund);
                    }
                    Err(e) => {
                        trace!("Worker[{worker_no}] fund_jjjz---2.4");

                        return Err(anyhow!(e));
                    }
                }
            }
            Err(e) => {
                trace!("Worker[{worker_no}] fund_jjjz---2.5");
                return Err(anyhow!(e));
            }
        }
    }
}

#[cfg(test)]
mod test {
    use crate::fund::fund_jjjz::FundJjjz;

    #[tokio::test]
    async fn test_fund_jjjz() {
        // let result = FundJjjz::fund_jjjz( "516760", 1, 20000).await;
        let result = FundJjjz::fund_jjjz(1, "000001", 1, 10000).await;

        // println!("result= {:?}", result);

        assert_eq!(result.is_ok(), true);
        if let Ok(fund_jjjz) = result {
            println!("fund_jjjz.data.lsjz_list.len= {:?}", fund_jjjz.data.lsjz_list.len());
            for (index, lsjz) in fund_jjjz.data.lsjz_list.iter().enumerate() {
                if index < 5 || index > fund_jjjz.data.lsjz_list.len() - 3 {
                    println!("lsjz[{}]= {:?}\n", index, lsjz);
                } else {
                    print!(".");
                }
            }
        }
    }
}
